package com.hshc.routeworkflow.rest.service.api.runtime.process;

import io.swagger.annotations.*;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@RestController
@Api(tags = {"Processes"}, description = "Manage Processes")
public class ActivityNodeRest {

    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;
    @Resource
    private RepositoryService repositoryService;

    @ApiOperation(value = "Get the current activity node from a process instance", tags = {"Process Instances"}, nickname = "getProcessInstance")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the process instance was found and returned."),
            @ApiResponse(code = 404, message = "Indicates the requested process instance was not found.")
    })
    @RequestMapping(value = "/runtime/process-instances/{processInstanceId}/current-activity-node", method = RequestMethod.GET, produces = "application/json")
    public CurrentActivityDefinitionResponse getCurrentActivity(@ApiParam(name = "processInstanceId", value = "The id of the process instance to get.") @PathVariable String processInstanceId) {

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
            throw new ActivitiIllegalArgumentException("No process instance found with id " + processInstanceId);
        }

        BpmnModel pojoModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());

        if (pojoModel == null || pojoModel.getLocationMap().isEmpty()) {
            throw new ActivitiException("Process definition could not be found with id " + processInstance.getProcessDefinitionId());
        }

        // Fetch process-instance activities
        List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();

        String activityId = null;
        if (CollectionUtils.isNotEmpty(activityInstances)) {
            for (HistoricActivityInstance activityInstance : activityInstances) {
                if (activityInstance.getEndTime() == null) {
                    activityId = activityInstance.getActivityId();
                    break;
                }
            }
        }

        FlowElement flowElement = pojoModel.getMainProcess().getFlowElement(activityId);

        return createCurrentActivityDefinitionResponse(flowElement);
    }

    private CurrentActivityDefinitionResponse createCurrentActivityDefinitionResponse(FlowElement flowElement) {
        CurrentActivityDefinitionResponse response = new CurrentActivityDefinitionResponse();

        response.setId(flowElement.getId());
        response.setName(flowElement.getName());
        response.setDocumentation(flowElement.getDocumentation());

        return response;
    }
}
